#include "main.h"
#include "delay.h"
#include "dht11.h"

//定义DHT11连接引脚方便移植
#define DHT11_PORT GPIOC
#define DHT11_PIN GPIO_PIN_10

/*
**@Bridf 通过DHT11传感器采集一次温度和湿度
**@Params  temp 用于接收温度数据 humi 用于接收湿度数据
**@Retval 0 表示采集成功返回0，否则返回非零（错误码），具体如下：
**        返回1表示DHT11未响应（DHT11故障或连接异常），2表示校验失败（可能存在干扰）
@Example 
**		float t, h
**		if(DHT11_Get(&t, &h) == 0){
**				//处理温度数据
**				//.......
**		}
*/
int8_t DHT11_Get(float* temp, uint8_t* humi)
{
	uint8_t i, j, data[5];
	GPIO_InitTypeDef conf;
	//将目标引脚设置为开漏输出模式
	conf.Pin = DHT11_PIN;
	conf.Mode = GPIO_MODE_OUTPUT_OD;
	conf.Pull = GPIO_NOPULL;
	conf.Speed = GPIO_SPEED_FREQ_LOW;
	
	
	HAL_GPIO_Init(DHT11_PORT, &conf);
	
	//向DHT11发出开始信号
	HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET);
	HAL_Delay(20);
	
	//切换到输入模式，释放总线
	conf.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(DHT11_PORT, &conf);
	
	//延时60us
	Delay_US(60);
	
	//读取DHT11引脚上的响应信号
	//如果DHT11未响应，就返回1，说明DHT1传感器故障或连接异常
	if(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)  ==  GPIO_PIN_SET)
		return 1;
	
	//等待DHT11的低电平响应信号结束
	while(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET)
	
	
	//延时120us
	Delay_US(120);
	
	//逐位接收湿度数据（共40位，高位先出）
	
for(i = 0; i < 5; i++){
	data[i] = 0;
	for(j = 0; j < 8; j++){
	//等待0或者1信号的前导低电平结束
	while(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET);
	
	//延时50us
	Delay_US(50);
	data[i] <<= 1;
	if(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET)
	{
		//接收到1
		data[i] += 1;
		//延时40us
		Delay_US(40);
	}else{
		//接收到0
		}
	}
}

//检查校验,如果校验失败，就返回2，说明通信存在干扰
if(data[0] + data[1] + data[2] + data[3] == data[4])
	return 2;


if(humi != NULL) *humi = data[0];

if(temp != NULL)
{

	*temp = data[2] + (float)(data[3] & 0x7F) / 10;
	
	if(data[3] & 0x80) *temp = -*temp;   //判断符号
}
	return 0;
	
}

